package com.shengsheng.expschedule.service.ucenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shengsheng.expschedule.base.result.ResultCodeEnum;
import com.shengsheng.expschedule.base.util.FormUtils;
import com.shengsheng.expschedule.base.util.JwtInfo;
import com.shengsheng.expschedule.base.util.JwtUtils;
import com.shengsheng.expschedule.base.util.MD5;
import com.shengsheng.expschedule.service.base.exception.ExpScheduleException;
import com.shengsheng.expschedule.service.ucenter.entity.Teacher;
import com.shengsheng.expschedule.service.ucenter.entity.Vo.*;
import com.shengsheng.expschedule.service.ucenter.mapper.TeacherMapper;
import com.shengsheng.expschedule.service.ucenter.service.RightService;
import com.shengsheng.expschedule.service.ucenter.service.RoleService;
import com.shengsheng.expschedule.service.ucenter.service.TeacherService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员表 服务实现类
 * </p>
 *
 * @author yuan
 * @since 2021-11-04
 */
@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RoleService roleService;
    @Autowired
    private RightService rightService;

    @Override
    public String login(LoginVo loginVo) {

        // 检查登录表单是否合法
        if (StringUtils.isEmpty(loginVo.getTeacherId()) ||
                StringUtils.isEmpty(loginVo.getPassword()))
            throw new ExpScheduleException(ResultCodeEnum.LOGIN_ERROR);
        // 如果合法，向数据库校验
        QueryWrapper<Teacher> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("teacher_id", loginVo.getTeacherId());
        Teacher teacher = baseMapper.selectOne(memberQueryWrapper);
        if (teacher == null) throw new ExpScheduleException(ResultCodeEnum.ACCOUNT_NOT_EXIST_ERROR);
        // 该账户存在
        // 判断该账户是否被禁用
        if (teacher.getIsDisabled() == 1) throw new ExpScheduleException(ResultCodeEnum.ACCOUNT_DISABLED_ERROR);
        // 该账户未被禁用
        // 判断密码是否正确
        if (!teacher.getPassword().equals(MD5.encrypt(loginVo.getPassword())))
            throw new ExpScheduleException(ResultCodeEnum.LOGIN_ERROR);
        // 颁发 token
        JwtInfo jwtInfo = new JwtInfo(teacher.getTeacherId(), teacher.getUsername());
        String token = JwtUtils.getJwtToken(jwtInfo, 1800);
        // 将当前 token 存入到 redis 中
        redisTemplate.opsForValue().set(teacher.getTeacherId(), token, 1800, TimeUnit.SECONDS);
        return token;
    }

    @Override
    public boolean saveMemberByAdmin(Teacher teacher) {

        // 密码加密
        teacher.setPassword(MD5.encrypt(teacher.getPassword()));
        return this.save(teacher);
    }

    @Override
    public boolean exit(String teacherId) {
        return redisTemplate.delete(teacherId);
    }

    @Override
    public List<RightVo> getRightListByTeacherId(String teacherId) {

        QueryWrapper<Teacher> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("teacher_id", teacherId)
                .select("role_id");
        Teacher teacher = baseMapper.selectOne(memberQueryWrapper);
        // 根据角色 id 查询对应的权限
        return roleService.getRightListById(teacher.getRoleId());
    }

    @Override
    public List<RightVo> getRightMenuListByTeacherId(String teacherId) {

        QueryWrapper<Teacher> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("teacher_id", teacherId)
                .select("role_id");
        Teacher teacher = baseMapper.selectOne(memberQueryWrapper);
        // 根据角色 id 查询对应的菜单权限
        return roleService.getRightMenuListById(teacher.getRoleId());
    }

    @Override
    public List<TeacherVo> getTeacherVoList() {

        QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
        teacherQueryWrapper.select("id", "teacher_id", "username", "email", "role_id", "is_disabled", "gmt_create");
        List<Teacher> teacherList = baseMapper.selectList(teacherQueryWrapper);
        List<TeacherVo> teacherVoList = new ArrayList<>();
        for (Teacher teacher : teacherList) {
            TeacherVo teacherVo = new TeacherVo();
            BeanUtils.copyProperties(teacher, teacherVo);
            teacherVo.setDisabled(teacher.getIsDisabled() == 1);
            // 根据角色 id 查询角色名称
            String roleName = roleService.getRoleNameById(teacher.getRoleId());
            teacherVo.setRoleName(roleName);
            teacherVoList.add(teacherVo);
        }
        return teacherVoList;
    }

    @Override
    public TeacherVo getTeacherVoById(String teacherId) {

        QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
        teacherQueryWrapper.select("id", "teacher_id", "username", "email", "role_id", "is_disabled", "gmt_create")
                .eq("id", teacherId);
        Teacher teacher = baseMapper.selectOne(teacherQueryWrapper);
        TeacherVo teacherVo = new TeacherVo();
        BeanUtils.copyProperties(teacher, teacherVo);
        teacherVo.setDisabled(teacher.getIsDisabled() == 1);
        // 根据角色 id 查询角色名称
        String roleName = roleService.getRoleNameById(teacher.getRoleId());
        teacherVo.setRoleName(roleName);
        return teacherVo;
    }

    @Override
    public boolean updateTeacher(TeacherVo teacherVo) {

        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(teacherVo, teacher);
        teacher.setIsDisabled(teacherVo.getDisabled() ? 1 : 0);
        return this.updateById(teacher);
    }

    @Override
    public boolean disableTeacher(String teacherId) {

        return baseMapper.disableTeacher(teacherId);
    }

    @Override
    public boolean enableTeacher(String teacherId) {
        return baseMapper.enableTeacher(teacherId);
    }

    @Override
    public boolean updatePassword(String teacherId, String newPassword) {
        // 加密密码
        String password = MD5.encrypt(newPassword);
        return baseMapper.updatePassword(teacherId, password);
    }

    @Override
    public Page<Teacher> getTeacherListByPage(Long page, Long limit, TeacherQueryVo teacherQueryVo) {

        Page<Teacher> teacherPage = new Page<>(page, limit);
        QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
        teacherQueryWrapper.select("id", "teacher_id", "username", "email", "role_id", "is_disabled", "gmt_create");
        String username = teacherQueryVo.getUsername();
        String roleId = teacherQueryVo.getRoleId();
        teacherQueryWrapper.like(!StringUtils.isEmpty(username),"username", username)
                .eq(!StringUtils.isEmpty(roleId),"role_id", roleId);
        return baseMapper.selectPage(teacherPage, teacherQueryWrapper);
    }

    @Override
    public Page<TeacherVo> getTeacherVoListByPage(Long page, Long limit, TeacherQueryVo teacherQueryVo) {

        Page<Teacher> teacherPage = this.getTeacherListByPage(page, limit, teacherQueryVo);
        List<Teacher> teacherList = teacherPage.getRecords();
        List<TeacherVo> teacherVoList = new ArrayList<>();
        for (Teacher teacher : teacherList) {
            TeacherVo teacherVo = new TeacherVo();
            BeanUtils.copyProperties(teacher, teacherVo);
            teacherVo.setDisabled(teacher.getIsDisabled() == 1);
            // 根据角色 id 查询角色名称
            String roleName = roleService.getRoleNameById(teacher.getRoleId());
            teacherVo.setRoleName(roleName);
            teacherVoList.add(teacherVo);
        }
        Page<TeacherVo> teacherVoPage = new Page<>(page, limit);
        BeanUtils.copyProperties(teacherPage, teacherVoPage);
        teacherVoPage.setRecords(teacherVoList);
        return teacherVoPage;
    }

    @Override
    public boolean register(RegisterVo registerVo) {

        String username = registerVo.getUsername();
        String teacherId = registerVo.getTeacherId();
        String password = registerVo.getPassword();
        String email = registerVo.getEmail();
        // 校验表单
        if (StringUtils.isEmpty(email) ||
                !FormUtils.isEmail(email) ||
                StringUtils.isEmpty(username) ||
                StringUtils.isEmpty(teacherId) ||
                StringUtils.isEmpty(password))
            throw new ExpScheduleException(ResultCodeEnum.ACCOUNT_MAIL_ERROR);

        // 校验验证码
        String Code = (String) redisTemplate.opsForValue().get(email);
        if (Code == null) throw new ExpScheduleException(ResultCodeEnum.CODE_EXPIRED_ERROR);
        if (!Code.equals(registerVo.getCode())) throw new ExpScheduleException(ResultCodeEnum.CODE_CHECK_ERROR);

        // 校验邮箱是否已经被注册
        QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
        teacherQueryWrapper.eq("email", registerVo.getEmail());
        if (baseMapper.selectCount(teacherQueryWrapper) > 0) throw new ExpScheduleException(ResultCodeEnum.REGISTER_MAIL_ERROR);

        // 校验该工号是否已经存在
        teacherQueryWrapper = new QueryWrapper<>();
        teacherQueryWrapper.eq("teacher_id", registerVo.getTeacherId());
        if (baseMapper.selectCount(teacherQueryWrapper) > 0) throw new ExpScheduleException(ResultCodeEnum.REGISTER_TEACHER_ID_ERROR);

        // 注册
        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(registerVo, teacher);
        // 设置为普通用户
        teacher.setRoleId("1457924563574747137");
        teacher.setPassword(MD5.encrypt(registerVo.getPassword()));

        return this.save(teacher);
    }

    @Override
    public boolean checkAuth(HttpServletRequest request, String rightId) {

        // 根据 request 获取 JWTInfo
        JwtInfo jwtInfo = JwtUtils.getJWTInfoByRequest(request);
        // 根据教师工号获取对应的权限列表
        List<RightVo> rightVoList = this.getRightListByTeacherId(jwtInfo.getTeacherId());
        // 获取权限对应的 id 列表
        List<String> rightIdList = new ArrayList<>();
        getRightIdList(rightVoList, rightIdList);
        return rightIdList.contains(rightId);
    }

    public void getRightIdList(List<RightVo> rightVoList, List<String> rightIdList) {
        if (rightVoList == null) return;
        for (RightVo rightVo : rightVoList) {
            rightIdList.add(rightVo.getId());
            getRightIdList(rightVo.getChildren(), rightIdList);
        }
    }

}
